package Prova::Exporter::TestBase;

use strict;
use warnings;
use Prova::FileMgr;
use File::Path;
use File::Temp qw(tempdir);
use Template;
use Data::Dumper;
use YAML;
use Encode qw/from_to/;
use MIME::Base64 qw/decode_base64/;

=head1 NAME

Prova::Exporter::TestBase

=head1 DESCRIPTION

none

=head1 METHODS

=cut

=head2 new

=cut

sub new {
    my $class = shift;
    my $self  = {};
    bless $self, $class;
}

=head2 type

=cut

sub type {
    return 'testbase';
}

=head2 output

=cut

sub output {
    my ( $self, $c, $workdir ) = @_;

    my $data = $c->controller( 'Exporter' )->get_all_data( $c );
    my $template_obj = $self->make_tmpl_obj( $c );
    my $testcases = $c->controller( 'Exporter' )->get_data( $c, 'testcases' );
    for my $id ( sort { $testcases->{$a}->order_by <=> $testcases->{$b}->order_by } keys %$testcases ) {
        my $testcase = $testcases->{$id};
        my $tags = $self->has_tags( $c, $data, $id );
        if ( ref $tags eq 'ARRAY' and @$tags ) {
            for my $tag ( @$tags ) {
                my $testcasedir = $self->make_testcase_dir( $c, $workdir, $tag->order_by, $tag->name );
                $self->make_testcase( $c, $testcasedir, $data, $testcase );
            }
        } else {
            my $testcasedir = $self->make_testcase_dir( $c, $workdir, 9999, 'none' );
            $self->make_testcase( $c, $testcasedir, $data, $testcase );
        }
    }

    my $testfiledir = $self->make_testfile_dir( $c, $workdir );
    $self->make_testfile( $c, $testfiledir );

    return 1;
}

=head2 has_tags

=cut

sub has_tags {
    my ( $self, $c, $data, $test_case_id ) = @_;

    my %map;
    my $testcases_tags = $data->{testcases_tags};
    if ( ref $testcases_tags eq 'ARRAY' and @$testcases_tags ) {
        for ( @$testcases_tags ) {
            push @{$map{$_->test_case_id->id}}, $_->tags_id;
        }
    }

    return $map{$test_case_id};
}

=head2 make_testcase_dir

=cut

sub make_testcase_dir {
    my ( $self, $c, $workdir, $tagid, $tagname ) = @_;

    my $testcasedir = sprintf( "$workdir/testcases/%04d_%s", $tagid, $tagname );
    unless ( -d $testcasedir ) {
        mkpath( $testcasedir );
        $c->log->info( "make dir: $testcasedir" );
    }
    return $testcasedir;
}

=head2 make_testcase

=cut

sub make_testcase {
    my ( $self, $c, $testcasedir, $data, $testcase ) = @_;

    my $file = sprintf( "$testcasedir/%05d.tb", $testcase->order_by );
    my $output;
    my %vars;
    $vars{testcase} = $testcase;
    if ( exists $data->{datablocks}->{$testcase->id} ) {
        for my $datablock ( @{$data->{datablocks}->{$testcase->id}} ) {

            my %datasections;
            for ( @{$data->{datasections}->{$datablock->id}}) {
                $datasections{$_->name} = eval { Load $_->value; };
                $c->log->info("===== can not load yaml : ".$@);
            }
            my $section = keys %datasections ? Dump \%datasections : '';
            $section =~ s/---//;

            my %test = (
                        datablock => $datablock,
                        datasections => $section,
                        pre_operations => $data->{pre_operations}->{$datablock->id},
                        assertions => $data->{assertions}->{$datablock->id},
                        post_operations => $data->{post_operations}->{$datablock->id},
                        accessors => $data->{accessors}->{$datablock->id},
                    );

            push @{ $vars{datablocks} }, \%test;
        }
    }

    my $tt = $self->tmpl_obj( $c );
    my $tmpl_path = $self->get_tmpl_path( $c );
    $tt->process( $tmpl_path, \%vars, \$output )|| die $tt->error, "\n";
    Prova::FileMgr->put( $file, $output );
    $c->log->debug("put file $file.");
}

=head2 make_testfile_dir

=cut

sub make_testfile_dir {
    my ( $self, $c, $workdir ) = @_;

    my $testfile_dir = "$workdir/testfiles";
    unless ( -d $testfile_dir ) {
        mkpath( $testfile_dir );
        $c->log->info( "make dir: $testfile_dir" );
    }
    return $testfile_dir;
}

=head2 make_testfile

=cut

sub make_testfile {
    my ( $self, $c, $testfiledir ) = @_;

    my @files = $c->model('DBIC::File')->search();
    foreach (@files) {
        my $file = sprintf("%s/%d_%d_%s.%s",
            $testfiledir,
            $_->data_block_id->id,
            $_->id,
            $_->name,
            $_->extention
        );
        Prova::FileMgr->put( $file, decode_base64( $_->body ) );
        $c->log->debug("put file $file.");
    }
}

=head2 make_tmpl_obj

=cut

sub make_tmpl_obj {
    my ( $self, $c ) = @_;

    my $tt = Template->new({
                            INCLUDE_PATH => Prova->path_to('templates'),
                        }) || die $Template::ERROR, "\n";
    $self->tmpl_obj( $c, $tt );
}

=head2 tmpl_obj

=cut

sub tmpl_obj {
    my $self = shift;
    my $c = shift;
    $self->set_tmpl_obj( $c, @_ ) if @_;
    $self->get_tmpl_obj( $c );
}

=head2 set_tmpl_obj

=cut

sub set_tmpl_obj {
    my ( $self, $c, $tt ) = @_;
    $c->stash->{obj_cache}->{tt} = $tt;
}

=head2 get_tmpl_obj

=cut

sub get_tmpl_obj {
    my ( $self, $c ) = @_;
    return $c->stash->{obj_cache}->{tt};
}

=head2 get_tmpl_path

=cut

sub get_tmpl_path {
    return 'export/testbase/testcase.tt';
}

=head2 encode

=cut

sub encode {
    my ( $self, $c, $testcasedir ) = @_;
    Encode::from_to( $testcasedir, 'utf8', 'euc-jp' );
}

=head1 AUTHOR

Shanon Inc, E<lt>http://www.shanon.co.jp/E<gt>

=head1 LICENSE

This library is free software, you can redistribute it and/or modify
it under the same terms as Perl itself.

=cut

1;
